package order

import (
	"booking/common/handler"
	"booking/common/utils"
	"booking/common/validator"
	"booking/models"
	"slices"
	"strings"

	"github.com/gin-gonic/gin"
)

func List(c *gin.Context) {
	var params struct {
		models.PageInfo
		OrderNo           string   `json:"order_no"`            // 单据编号
		CustomerName      string   `json:"customer_name"`       // 客户名称
		SignDateStart     string   `json:"sign_date_start"`     // 签单日期
		SignDateEnd       string   `json:"sign_date_end"`       // 签单日期
		PushDateStart     string   `json:"push_date_start"`     // 推送时间
		PushDateEnd       string   `json:"push_date_end"`       // 推送时间
		CompleteDateStart string   `json:"complete_date_start"` // 完成日期
		CompleteDateEnd   string   `json:"complete_date_end"`   // 完成日期
		Source            string   `json:"source"`              // 订单来源
		Status            *int     `json:"status"`              // 订单状态
		Courier           string   `json:"courier"`             // 物流公司
		TrackingNo        string   `json:"tracking_no"`         // 快递单号
		ProductDesc       string   `json:"product_desc"`        // 商品服务
		MinAmount         *float64 `json:"min_amount"`          // 应收金额
		MaxAmount         *float64 `json:"max_amount"`          // 应收金额
	}

	if err := c.ShouldBindJSON(&params); err != nil {
		handler.Error(validator.Translate(err), c)
		return
	}

	var orderList []models.Order
	var total int64
	query := models.Db.
		Model(models.Order{}).
		Table("`order` as o").
		Preload("Courier").
		Preload("Product").
		Joins("LEFT JOIN order_courier as oc ON oc.order_no = o.order_no").
		Joins("LEFT JOIN order_product as op ON op.order_no = o.order_no").
		Group("o.order_no")

	if params.OrderNo != "" {
		query.Where("o.order_no LIKE ?", "%"+params.OrderNo+"%")
	}

	if params.CustomerName != "" {
		query.Where("o.customer_name LIKE ?", "%"+params.CustomerName+"%")
	}
	if params.SignDateStart != "" {
		query.Where("o.sign_date >= ?", params.SignDateStart)
	}
	if params.SignDateEnd != "" {
		query.Where("o.sign_date <=", params.SignDateEnd)
	}
	if params.PushDateStart != "" {
		query.Where("o.push_date >= ?", params.PushDateStart)
	}
	if params.PushDateEnd != "" {
		query.Where("o.push_date <=", params.PushDateEnd)
	}
	if params.CompleteDateStart != "" {
		query.Where("o.complete_date >= ?", params.CompleteDateStart)
	}
	if params.CompleteDateEnd != "" {
		query.Where("o.complete_date <=", params.CompleteDateEnd)
	}
	if params.Source != "" {
		query.Where("o.source = ?", params.Source)
	}
	if params.Status != nil {
		query.Where("o.status = ?", params.Status)
	}

	if params.Courier != "" {
		query.Where("oc.courier LIKE ?", "%"+params.Courier+"%")
	}
	if params.TrackingNo != "" {
		query.Where("oc.tracking_no LIKE ?", "%"+params.TrackingNo+"%")
	}
	if params.ProductDesc != "" {
		query.Where("op.product_desc LIKE ?", "%"+params.ProductDesc+"%")
	}

	query.Count(&total)
	var data = handler.Data{
		TotalCount: total,
		PageIndex:  params.DefPage(),
		PageSize:   params.DefPageSize(),
	}
	query.Offset(params.Offset()).
		Limit(params.DefPageSize()).
		Order("id desc").
		Find(&orderList)
	var list = make([]map[string]any, 0)
	for _, v := range orderList {
		trackingNos := slices.Collect(func(yield func(string) bool) {
			for _, m := range v.Courier {
				if !yield(m.TrackingNo) {
					return
				}
			}
		})
		trackingNo := strings.Join(trackingNos, "、")

		productDescs := slices.Collect(func(yield func(string) bool) {
			for _, m := range v.Product {
				if !yield(m.ProductDesc) {
					return
				}
			}
		})
		productDesc := strings.Join(productDescs, "、")
		list = append(list, map[string]any{
			"order_no":      v.OrderNo,
			"customer_name": v.CustomerName,
			"sign_date":     utils.FormatDate(v.SignDate),
			"push_date":     utils.FormatDate(v.PushDate),
			"complete_date": utils.FormatDate(v.CompleteDate),
			"status":        v.Status,
			"status_label":  models.OrderStatusMap[v.Status],
			"tracking_no":   trackingNo,
			"product_desc":  productDesc,
			"total_amount":  v.TotalAmount,
			"source":        v.Source,
			"updated_time":  v.UpdatedTime,
		})
	}
	data.List = list
	data.Format()
	handler.Success(data, c)
}
